package data;

import constants.TileTypes;

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.io.Serializable;
import java.util.HashMap;

/**
 * data
 *
 * @author Jared Moore
 * @date 10/8/13
 */
public class Tile implements Serializable {
	public static final HashMap<TileTypes, Integer[]> TILE_VALUES = new HashMap<>();
	public static final HashMap<TileTypes, BufferedImage> TILE_ICONS = new HashMap<>();
	private final boolean isTown;
	private Integer[] values = new Integer[4];
	private Player owner, onTile;
	private transient BufferedImage icon;
	private Point tileLocation;
	private MULE mule;
	private TileTypes type;

	static {
		Integer[] plainValues = {2, 3, 1, 1},
				riverValues = {4, 2, 0, 0},
				mountain1Values = {1, 1, 2, 2},
				mountain2Values = {1, 1, 3, 3},
				mountain3Values = {1, 1, 4, 4};
		TILE_VALUES.put(TileTypes.PLAIN, plainValues);
		TILE_VALUES.put(TileTypes.RIVER, riverValues);
		TILE_VALUES.put(TileTypes.ONE_MOUNTAIN, mountain1Values);
		TILE_VALUES.put(TileTypes.TWO_MOUNTAINS, mountain2Values);
		TILE_VALUES.put(TileTypes.THREE_MOUNTAINS, mountain3Values);

		try {
			TILE_ICONS.put(TileTypes.PLAIN, ImageIO.read(new File("res/tiles/plain.jpg")));
			TILE_ICONS.put(TileTypes.TOWN, ImageIO.read(new File("res/tiles/town.jpg")));
			TILE_ICONS.put(TileTypes.RIVER, ImageIO.read(new File("res/tiles/river.jpg")));
			TILE_ICONS.put(TileTypes.ONE_MOUNTAIN, ImageIO.read(new File("res/tiles/mountain1.jpg")));
			TILE_ICONS.put(TileTypes.TWO_MOUNTAINS, ImageIO.read(new File("res/tiles/mountain2.jpg")));
			TILE_ICONS.put(TileTypes.THREE_MOUNTAINS, ImageIO.read(new File("res/tiles/mountain3.jpg")));
		} catch (IOException e) {
			System.err.println("Tile image not found");
			System.exit(1);
		}
	}

	public Tile(TileTypes type, Point tileLocation) {
		this.type = type;
		owner = null;
		onTile = null;
		if (type == TileTypes.TOWN) {
			isTown = true;
			setIcon();
		} else {
			isTown = false;
			values = TILE_VALUES.get(type);
			setIcon();
		}
		this.tileLocation = tileLocation;
	}

	public void setIcon() {
		icon = TILE_ICONS.get(type);
	}

	public void draw(Graphics g, int tileWidth, int tileHeight, boolean setup, Player currPlayer) {
		g.drawImage(icon, tileLocation.x * tileWidth, tileLocation.y * tileHeight, tileWidth, tileHeight, null);
		if (owner != null) {
			try {
				Image border = ImageIO.read(new File(String.format("res/borders/%s.png",
						owner.getColorText())));
				g.drawImage(border, tileLocation.x * tileWidth,
						tileLocation.y * tileHeight, tileWidth, tileHeight, null);
				if (mule != null) {
					g.drawImage(ImageIO.read(new File("res/MULES/" + Player.COLOR_NAMES.get(owner.getColors()) +
							"/" + MULE.MULE_TYPES_NAMES.get(mule.getOutfit()) + "M.U.L.E.png")), tileLocation.x *
							tileWidth, tileLocation.y * tileHeight, tileWidth / 2, tileHeight / 2, null);
				}
			} catch (IOException e) {
				System.err.printf("%s border does not exist", owner.getColorText());
				System.exit(1);
			}
		}
		if (onTile != null && !setup && onTile == currPlayer) {
			onTile.draw(g, tileWidth, tileHeight, tileLocation);
		}
	}

	public void draw(Graphics g, int tileWidth, int tileHeight) {
		try {
			Image border = ImageIO.read(new File("res/borders/black.png"));
			g.drawImage(border, tileLocation.x * tileWidth, tileLocation.y * tileHeight, tileWidth, tileHeight, null);
		} catch (IOException e) {
			System.err.printf("%s border does not exist", owner.getColor());
			System.exit(1);
		}

	}

	public void placeMule(MULE freeMule) {
		mule = freeMule;
	}

	public int[] calculateProduction() {
		int production[] = new int[4];
		if (mule != null) {
			if (owner.getEnergy() > 0) {
				owner.decrementEnergy(1);
				switch (mule.getOutfit()) {
					case FOOD:
						production[0] = values[0];
						break;
					case ENERGY:
						production[1] = values[1];
						break;
					case ORE:
						production[2] = values[2];
						break;
					case CRYSTITE:
						production[3] = values[3];
				}
			}
		}
		return production;
	}

	public Player getOwner() {
		return owner;
	}

	public void setOwner(Player owner) {
		this.owner = owner;
	}

	public boolean isTown() {
		return isTown;
	}

	public Player getOnTile() {
		return onTile;
	}

	public MULE getMule() {
		return (mule);
	}

	public void setOnTile(Player onTile) {
		this.onTile = onTile;
	}

	public Point getTileLocation() {
		return tileLocation;
	}
}
